package com.aizuda.boot.modules.business.contract.service.impl;

import com.aizuda.boot.modules.business.contract.dto.SingleResponse;
import com.aizuda.boot.modules.business.contract.entity.ContractFieldEntity;
import com.aizuda.boot.modules.business.contract.entity.ContractModuleEntity;
import com.aizuda.boot.modules.business.contract.entity.ContractModuleFieldEntity;
import com.aizuda.boot.modules.business.contract.entity.vo.ContractFieldShowDTO;
import com.aizuda.boot.modules.business.contract.entity.vo.FieldConfigRespDTO;
import com.aizuda.boot.modules.business.contract.entity.vo.FieldsVO;
import com.aizuda.boot.modules.business.contract.mapper.ContractFieldMapper;
import com.aizuda.boot.modules.business.contract.service.ContractFieldService;
import com.aizuda.boot.modules.business.contract.service.ContractModuleFieldService;
import com.aizuda.boot.modules.business.contract.service.ContractModuleService;
import com.aizuda.boot.modules.business.template.utils.FieldCodeGenerator;
import com.aizuda.boot.modules.common.constant.RedisKeyConstant;
import com.aizuda.boot.modules.common.constant.enums.*;
import com.aizuda.boot.modules.common.util.RedisService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.event.ApplicationContextEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 合同字段定义Service实现类
 *
 * @Author sangyirong
 * @Version 1.0
 * @Date 2025/5/20 13:36
 */
@Slf4j
@Service
public class ContractFieldServiceImpl extends ServiceImpl<ContractFieldMapper, ContractFieldEntity> implements ContractFieldService {

    @Resource
    private RedisService redisService;

    @Lazy
    @Resource
    private ContractExe contractExe;

    @Resource
    private ContractModuleService contractModuleService;

    @Override
    public FieldConfigRespDTO getFieldConfig() {
        // 1. 查询所有DROPDOWN_SINGLE类型的启用字段
        LambdaQueryWrapper<ContractFieldEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ContractFieldEntity::getFieldType, FieldTypeEnum.DROPDOWN_SINGLE.getKey())
                .eq(ContractFieldEntity::getIsEnabled, true)
                .orderByAsc(ContractFieldEntity::getId);

        List<ContractFieldEntity> dropdownFields = this.list(queryWrapper);

        // 2. 构建返回结果
        FieldConfigRespDTO response = new FieldConfigRespDTO();
        List<FieldConfigRespDTO.DropdownFieldConfig> configs = new ArrayList<>();

        // 3. 特殊处理：添加fieldId为0的合同状态枚举
        FieldConfigRespDTO.DropdownFieldConfig statusConfig = new FieldConfigRespDTO.DropdownFieldConfig();
        statusConfig.setFieldId(0L);
        statusConfig.setFieldName("合同状态");

        List<FieldConfigRespDTO.FieldOption> statusOptions = new ArrayList<>();
        for (ContractStatusEnum enumValue : ContractStatusEnum.values()) {
            // 过滤掉审核中状态
            if ("IN_NEGOTIATION".equals(enumValue.getCode())) {
                continue;
            }
            FieldConfigRespDTO.FieldOption option = new FieldConfigRespDTO.FieldOption();
            option.setCode(enumValue.getCode());
            option.setName(enumValue.getMsg());
            statusOptions.add(option);
        }
        statusConfig.setOptions(statusOptions);
        configs.add(statusConfig);

        // 4. 处理其他DROPDOWN_SINGLE字段
        for (ContractFieldEntity field : dropdownFields) {
            FieldConfigRespDTO.DropdownFieldConfig config = new FieldConfigRespDTO.DropdownFieldConfig();
            config.setFieldId(field.getId());
            config.setFieldName(field.getFieldName());

            // 根据字段名称获取对应的枚举选项
            List<FieldConfigRespDTO.FieldOption> options = getFieldOptionsByName(field.getFieldName(), field.getFieldOptions());
            config.setOptions(options);

            configs.add(config);
        }

        response.setDropdownFields(configs);
        return response;
    }

    @Override
    public SingleResponse<List<FieldsVO>> allFields() {
        List<FieldsVO> result = new ArrayList<>();
        List<ContractFieldEntity> list = this.list();
        if (CollectionUtils.isEmpty(list)) {
            return SingleResponse.of(result);
        }
        Map<Long, List<ContractFieldEntity>> child = list.stream().filter(item -> null != item.getParentFieldId())
                .collect(Collectors.groupingBy(ContractFieldEntity::getParentFieldId));
        list.stream().filter(item -> null == item.getParentFieldId()).forEach(item -> {
            FieldsVO fieldsVO = new FieldsVO();
            fieldsVO.setId(item.getId());
            fieldsVO.setFieldName(item.getFieldName());
            fieldsVO.setCode(item.getCode());
            fieldsVO.setFieldType(item.getFieldType());
            if (StringUtils.hasText(item.getFieldOptions())) {
                fieldsVO.setFieldOptionMap(JSON.parseObject(item.getFieldOptions(), Map.class));
            }
            if (child.containsKey(item.getId())) {
                ArrayList<FieldsVO> childList = new ArrayList<>();
                child.get(item.getId()).forEach(childItem -> {
                    FieldsVO childFieldsVO = new FieldsVO();
                    childFieldsVO.setId(childItem.getId());
                    childFieldsVO.setFieldName(childItem.getFieldName());
                    childFieldsVO.setCode(childItem.getCode());
                    childFieldsVO.setFieldType(childItem.getFieldType());
                    if (StringUtils.hasText(childItem.getFieldOptions())) {
                        childFieldsVO.setFieldOptionMap(JSON.parseObject(childItem.getFieldOptions(), Map.class));
                    }
                    childList.add(childFieldsVO);
                });
                fieldsVO.setChildren(childList);
            }
            result.add(fieldsVO);
        });
        return SingleResponse.of(result);
    }

    /**
     * 根据字段名称获取对应的枚举选项
     *
     * @param fieldName    字段名称
     * @param fieldOptions 字段选项JSON字符串
     * @return 选项列表
     */
    private List<FieldConfigRespDTO.FieldOption> getFieldOptionsByName(String fieldName, String fieldOptions) {
        List<FieldConfigRespDTO.FieldOption> options = new ArrayList<>();

        try {
            // 根据字段名称匹配对应的枚举类
            switch (fieldName) {
                case "框架协议":
                    for (FrameworkAgreementEnum enumValue : FrameworkAgreementEnum.values()) {
                        FieldConfigRespDTO.FieldOption option = new FieldConfigRespDTO.FieldOption();
                        option.setCode(enumValue.getCode());
                        option.setName(enumValue.getMsg());
                        options.add(option);
                    }
                    break;

                case "收支类型":
                    for (IncomeExpenseTypeEnum enumValue : IncomeExpenseTypeEnum.values()) {
                        FieldConfigRespDTO.FieldOption option = new FieldConfigRespDTO.FieldOption();
                        option.setCode(enumValue.getCode());
                        option.setName(enumValue.getMsg());
                        options.add(option);
                    }
                    break;

                case "计价方式":
                    for (PricingMethodEnum enumValue : PricingMethodEnum.values()) {
                        FieldConfigRespDTO.FieldOption option = new FieldConfigRespDTO.FieldOption();
                        option.setCode(enumValue.getCode());
                        option.setName(enumValue.getMsg());
                        options.add(option);
                    }
                    break;

                case "创建方式":
                    for (CreationMethod enumValue : CreationMethod.values()) {
                        FieldConfigRespDTO.FieldOption option = new FieldConfigRespDTO.FieldOption();
                        option.setCode(enumValue.getCode());
                        option.setName(enumValue.getMsg());
                        options.add(option);
                    }
                    break;

                case "合同期限类型":
                    for (ContractTermEnum enumValue : ContractTermEnum.values()) {
                        FieldConfigRespDTO.FieldOption option = new FieldConfigRespDTO.FieldOption();
                        option.setCode(enumValue.getCode());
                        option.setName(enumValue.getMsg());
                        options.add(option);
                    }
                    break;

                default:
                    // 如果没有匹配的枚举类，尝试解析fieldOptions中的JSON数据
                    if (StringUtils.hasText(fieldOptions)) {
                        try {
                            List<String> optionList = JSON.parseArray(fieldOptions, String.class);
                            for (String optionStr : optionList) {
                                FieldConfigRespDTO.FieldOption option = new FieldConfigRespDTO.FieldOption();
                                option.setCode(optionStr);
                                option.setName(optionStr);
                                options.add(option);
                            }
                        } catch (Exception e) {
                            log.warn("解析字段选项失败，字段名称: {}, fieldOptions: {}", fieldName, fieldOptions, e);
                        }
                    }
                    break;
            }
        } catch (Exception e) {
            log.error("获取字段选项失败，字段名称: {}", fieldName, e);
        }

        return options;
    }

    /**
     * 初始化字段配置,将字段缓存到redis中
     */
    @EventListener(ApplicationReadyEvent.class)
    public void initFieldConfig() {
        log.info("项目启动成功开始缓存字段");
        List<ContractFieldEntity> list = this.list();
        if (CollectionUtils.isEmpty(list)) {
            log.info("字段为空，无缓存");
            return;
        }
        list.forEach(item -> {
            redisService.setHashObject(RedisKeyConstant.Business.CONTRACT_FIELD_PREFIX + item.getId(), item);
        });
        log.info("项目启动成功缓存字段完成,共缓存字段: {} 个", list.size());
        log.info("成功开始缓存模块字段关联");
    }

    @EventListener(ApplicationReadyEvent.class)
    public void initModuleField() {
        log.info("项目启动成功开始缓存模块字段关联");
        List<ContractModuleEntity> list = contractModuleService.list();
        if (CollectionUtils.isEmpty(list)) {
            log.info("模块字段关联为空，无缓存");
            return;
        }
        list.forEach(module -> {
            // 删除缓存
            redisService.deleteObject(RedisKeyConstant.Business.CONTRACT_MODULE_PREFIX + module.getId());
            // 添加缓存
            SingleResponse<List<ContractFieldShowDTO>> listSingleResponse = contractExe.listContractFields(module.getId());
            if (listSingleResponse.isSuccess()) {
                List<ContractFieldShowDTO> data = listSingleResponse.getData();
                if (CollectionUtils.isEmpty(data)) {
                    log.info("模块字段关联为空，无缓存");
                    return;
                }
                redisService.setCacheList(RedisKeyConstant.Business.CONTRACT_MODULE_PREFIX + module.getId(), data);
            }
        });
        log.info("项目启动成功缓存模块字段关联完成,共缓存模块字段关联: {} 个", list.size());
    }
} 